<template>
  <div 
    class="image-card" 
    @click="$emit('image-click', image)"
    :style="{ height: cardHeight + 'px' }"
    :data-image-path="image.path"
  >
    <div class="image-container">
      <img
        v-if="isVisible"
        :src="imageSrc"
        :alt="image.name"
        @load="onImageLoad"
        @error="onImageError"
        class="image"
        :style="{ opacity: imageLoaded ? 1 : 0 }"
      />
      <div v-if="!isVisible" class="loading-placeholder">
        <div class="loading-spinner"></div>
      </div>
      <div v-if="isVisible && !imageLoaded && !imageError" class="loading-placeholder">
        <div class="loading-spinner"></div>
      </div>
      <div v-if="imageError" class="error-placeholder">
        <span>加载失败</span>
      </div>
    </div>
    
    <div class="image-info">
      <div class="image-name">{{ image.name }}</div>
      <div class="image-meta">
        <span class="file-size">{{ formatFileSize(image.size) }}</span>
        <span class="file-date">{{ formatDate(image.modified) }}</span>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed, onMounted, onUnmounted } from 'vue';

export default {
  name: 'ImageCard',
  props: {
    image: {
      type: Object,
      required: true
    },
    folderPath: {
      type: String,
      required: true
    }
  },
  emits: ['image-click'],
  setup(props) {
    const imageLoaded = ref(false);
    const imageError = ref(false);
    const cardHeight = ref(200); // 默认高度
    const isVisible = ref(false);
    const observer = ref(null);

    const imageSrc = computed(() => {
      // 使用 file:// 协议加载本地图片
      return `file://${props.image.path}`;
    });

    const onImageLoad = (event) => {
      imageLoaded.value = true;
      imageError.value = false;
      
      // 根据图片实际尺寸计算卡片高度，保持宽高比
      const img = event.target;
      const aspectRatio = img.naturalHeight / img.naturalWidth;
      const baseWidth = 200; // 基础宽度
      cardHeight.value = Math.max(150, Math.min(400, baseWidth * aspectRatio));
    };

    const onImageError = () => {
      imageError.value = true;
      imageLoaded.value = false;
    };

    const formatFileSize = (bytes) => {
      if (bytes === 0) return '0 B';
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
    };

    const formatDate = (date) => {
      return new Date(date).toLocaleDateString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit'
      });
    };

    // 懒加载实现
    onMounted(() => {
      if ('IntersectionObserver' in window) {
        observer.value = new IntersectionObserver(
          (entries) => {
            entries.forEach((entry) => {
              if (entry.isIntersecting) {
                isVisible.value = true;
                observer.value?.unobserve(entry.target);
              }
            });
          },
          {
            rootMargin: '50px' // 提前50px开始加载
          }
        );
        
        const cardElement = document.querySelector(`[data-image-path="${props.image.path}"]`);
        if (cardElement) {
          observer.value.observe(cardElement);
        }
      } else {
        // 不支持 IntersectionObserver 时直接显示
        isVisible.value = true;
      }
    });

    onUnmounted(() => {
      if (observer.value) {
        observer.value.disconnect();
      }
    });

    return {
      imageLoaded,
      imageError,
      cardHeight,
      imageSrc,
      isVisible,
      onImageLoad,
      onImageError,
      formatFileSize,
      formatDate
    };
  }
};
</script>

<style scoped>
.image-card {
  background: white;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  cursor: pointer;
  transition: all 0.2s ease;
  position: relative;
}

.image-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(0,0,0,0.15);
}

.image-container {
  position: relative;
  width: 100%;
  height: calc(100% - 60px);
  overflow: hidden;
}

.image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity 0.3s ease;
}

.loading-placeholder,
.error-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f5f5;
  color: #666;
}

.loading-spinner {
  width: 24px;
  height: 24px;
  border: 2px solid #f3f3f3;
  border-top: 2px solid #4285f4;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.image-info {
  padding: 8px 12px;
  height: 60px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: white;
}

.image-name {
  font-size: 12px;
  font-weight: 500;
  color: #333;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.image-meta {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: #666;
}

.file-size,
.file-date {
  flex: 1;
}
</style>
